1 module dlangui_bearlibterminal.fonts;
2 
3 import dlangui;
4 
5 class BearLibFontManager : FontManager
6 {
7     private static FontRef font;
8 
9     static this()
10     {
11         font = new BearLibFont;
12     }
13 
14     override:
15 
16     ref FontRef getFont(int size, int weight, bool italic, FontFamily family, string face)
17     {
18         return font;
19     }
20 
21     void checkpoint()
22     {
23         assert(false, "Isn't implemented");
24     }
25 
26     void cleanup()
27     {
28         assert(false, "Isn't implemented");
29     }
30 }
31 
32 class BearLibFont : Font
33 {
34     private Glyph _glyph;
35 
36     this() {
37         _spaceWidth = 1;
38         _glyph.blackBoxX = 1;
39         _glyph.blackBoxY = 1;
40         _glyph.widthPixels = 1;
41         _glyph.widthScaled = 1 << 6;
42         _glyph.originX = 0;
43         _glyph.originY = 0;
44         _glyph.subpixelMode = SubpixelRenderingMode.None;
45         _glyph.glyph = [0];
46     }
47 
48     private static bool isHotkeySymbol(in dchar c, uint textFlags)
49     {
50         return c == '&' && (textFlags & (
51                 TextFlag.UnderlineHotKeys |
52                 TextFlag.HotKeys |
53                 TextFlag.UnderlineHotKeysWhenAltPressed
54             ));
55     }
56 
57     override:
58 
59     int size() @property { return 1; }
60     int height() @property { return 1; }
61     int weight() @property { return 400; }
62     int baseline() @property { return 0; }
63     bool italic() @property { return false; }
64     string face() @property { return "console"; }
65     FontFamily family() @property { return FontFamily.MonoSpace; }
66     bool isNull() @property { return false; }
67     void checkpoint() {} /// clear usage flags for all entries
68     void cleanup() {} /// removes entries not used after last call of checkpoint() or cleanup()
69     void clearGlyphCache() {}
70 
71     Glyph* getCharGlyph(dchar ch, bool withImage)
72     {
73         return &_glyph;
74     }
75 
76     import BearLibTerminal: BT = terminal;
77 
78     //TODO: use tabSize and tabOffset for printing
79     void drawText(DrawBuf drawBuf, int x, int y, in dchar[] text, uint argb_color, int tabSize, int tabOffset, uint textFlags)
80     {
81         import dlangui_bearlibterminal.drawbuf: BearLibDrawBuf;
82 
83         const bool defaultUnderline = (textFlags & TextFlag.Underline) != 0;
84         bool underline = defaultUnderline;
85 
86         foreach(dchar c; text)
87         {
88             if(isHotkeySymbol(c, textFlags))
89             {
90                 underline = true;
91             }
92             else
93             {
94                 auto buf = cast(BearLibDrawBuf) drawBuf;
95 
96                 buf.drawCharWithEffects(x, y, c, underline, argb_color);
97 
98                 underline = defaultUnderline;
99                 x++;
100             }
101         }
102     }
103 
104     int measureText(const dchar[] text, ref int[] widths, int maxWidth, int tabSize, int tabOffset, uint textFlags)
105     {
106         int len;
107 
108         foreach(const c; text)
109         {
110             if(!isHotkeySymbol(c, textFlags))
111                 len++;
112         }
113 
114         if(len > maxWidth)
115             len = maxWidth;
116 
117         if(widths.length < len)
118             widths.length = len;
119 
120         foreach(int i; 0 .. len)
121             widths[i] = i+1;
122 
123         Log.v(__FUNCTION__~" len="~len.to!string~" widths="~widths.to!string);
124 
125         return len;
126     }
127 
128     // FIXME
129     Point measureMultilineText(const dchar[] text, int maxLines, int maxWidth, int tabSize, int tabOffset, uint textFlags)
130     {
131         auto dim = BT.measure(text.to!string);
132 
133         if(dim.width > maxWidth)
134             dim.width = maxWidth;
135 
136         if(dim.height > maxLines)
137             dim.height = maxLines;
138 
139         Point ret = {x: dim.width, y: dim.height};
140 
141         return ret;
142     }
143 }